package com.wanxi.config.security;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.wanxi.model.Manager;
import com.wanxi.util.JwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.SignatureException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.Objects;


@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //TODO 获取Token
        String token = request.getHeader("Token");
        //判断请求是否有token，没有则直接放行
        if (Objects.isNull(token)) {
            filterChain.doFilter(request, response);
            //一定要放行，避免运行后面的代码
            return;
        }
        //TODO 解析Token
        Claims claims;
        try {
            claims = JwtUtil.parseJWT(token);
        } catch (JwtException e){
            filterChain.doFilter(request,response);
            return;
        }
        //判断Token是否过期
        long managerId = 0;
        if (claims.getExpiration().after(new Date())) {
            managerId = Long.parseLong(claims.get("managerId").toString());
        }
        //TODO 解析的Token从redis中获取值
        String managerString = stringRedisTemplate.opsForValue().get("loginManager:" + managerId);
        //判断redis中是否有该用户id信息,有则取出并转换成Manager对象
        if (managerString != null) {
            Manager manager = JSON.parseObject(managerString, new TypeReference<Manager>() {
            });
            //TODO 存入securityContextHolder中
            UsernamePasswordAuthenticationToken authenticationToken
                    = new UsernamePasswordAuthenticationToken(manager.getManagerName(), manager.getPassword(), manager.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
        filterChain.doFilter(request, response);
    }
}
